package com.environment;


import com.knowledge.facts.FoodFact;
import com.knowledge.facts.FactRepository;
import com.environment.Tile;
import com.environment.Percept;
import com.environment.AbstractSystemInputParser;
import com.knowledge.facts.EnemyAntFact;
import com.knowledge.facts.EnemyHillFact;
import com.knowledge.facts.Fact;
import com.knowledge.facts.FriendlyAntFact;
import com.knowledge.facts.FriendlyHillFact;
import com.knowledge.facts.IntendedLocationFact;
import com.knowledge.facts.UnexploredFact;
import com.knowledge.facts.paths.PathFact;
import java.util.HashSet;
import java.util.Set;

/**
 * Provides basic game state handling.
 */
public abstract class Bot extends AbstractSystemInputParser {
    private Percept environment;
    
    /**
     * {@inheritDoc}
     */
    @Override
    public void setup(int loadTime, int turnTime, int rows, int cols, int turns, int viewRadius2,
            int attackRadius2, int spawnRadius2) {
            Percept instance = Percept.getInstance();
            instance.initialize(loadTime, turnTime, rows, cols, turns, viewRadius2, attackRadius2, spawnRadius2);
            setPercept(instance);
    }
    
    /**
     * Returns game state information.
     * 
     * @return game state information
     */
    public Percept getPercept() {
        return environment;
    }
    
    /**
     * Sets game state information.
     * 
     * @param ants game state information to be set
     */
    protected void setPercept(Percept env) {
        this.environment = env;
    }
    
    /**
     * {@inheritDoc}
     */
    @Override
    public void beforeUpdate() {
        environment.setTurnStartTime(System.currentTimeMillis());
        environment.clearMyAnts();
        environment.clearEnemyAnts();
        environment.getFoodTiles().clear();
        FactRepository.getInstance().removeAllInstances(FoodFact.class);
        FactRepository.getInstance().removeAllInstances(IntendedLocationFact.class);
    }
    
    /**
     * {@inheritDoc}
     */
    @Override
    public void addWater(int row, int col) {
        environment.update(Ilk.WATER, new Tile(row, col), 0);
    }
    
    /**
     * {@inheritDoc}
     */
    @Override
    public void addAnt(int row, int col, int owner) {
        environment.update(owner > 0 ? Ilk.ENEMY_ANT : Ilk.MY_ANT, new Tile(row, col), owner);
    }
    
    /**
     * {@inheritDoc}
     */
    @Override
    public void addFood(int row, int col) {
        environment.update(Ilk.FOOD, new Tile(row, col),0);
    }
    
    /**
     * {@inheritDoc}
     */
    @Override
    public void removeAnt(int row, int col, int owner) {
        environment.update(Ilk.DEAD, new Tile(row, col),owner);
    }
    
    /**
     * {@inheritDoc}
     */
    @Override
    public void addHill(int row, int col, int owner) {
        environment.updateHills(owner, new Tile(row, col));
    }
    
    /**
     * {@inheritDoc}
     */
    @Override
    public void afterUpdate() {
        Set<Fact> pathFacts = FactRepository.getInstance().getPathFacts();
        Set<Fact> removeFacts = new HashSet<Fact>(pathFacts);
        
        for (Fact fact: FactRepository.getInstance().getInstances(FriendlyAntFact.class)) {
            FriendlyAntFact ant = (FriendlyAntFact) fact;
            for (Fact rawPath: pathFacts) {
                PathFact path = (PathFact) rawPath;
                // to associate a path: the source must equal the ants position and it must have steps remaining.
                if (path.getSource().equals(ant.getLocation()) && !path.getLocation().equals(ant.getLocation()) && path.getRemainingSteps() > 0) {
                    ant.setReference(path);
                    removeFacts.remove(path);
                } 
            }
        }
        
        FactRepository.getInstance().removePaths(removeFacts);
        
        
        
//        System.err.println("size stats:");
          System.err.println("      kills: "+environment.getKillString());
//        System.err.println("      paths: "+FactRepository.getInstance().getPathFacts().size()+"/"+pathFacts.size());
//        System.err.println("       ants: "+FactRepository.getInstance().getInstances(FriendlyAntFact.class).size());
//        System.err.println("      hills: "+FactRepository.getInstance().getInstances(FriendlyHillFact.class).size());
//        System.err.println("     enemys: "+FactRepository.getInstance().getInstances(EnemyAntFact.class).size());
//        System.err.println(" enemyhills: "+FactRepository.getInstance().getInstances(EnemyHillFact.class).size());
//        System.err.println("       food: "+FactRepository.getInstance().getInstances(FoodFact.class).size());
//        System.err.println(" unexplored: "+FactRepository.getInstance().getInstances(UnexploredFact.class).size());
//        System.err.println("   intended: "+FactRepository.getInstance().getInstances(IntendedLocationFact.class).size());

    }
}
